package com.zjhn.ds.netty.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zjhn.ds.common.Constant;
import com.zjhn.ds.domain.vo.StationStationTimeVo;
import com.zjhn.ds.utils.RestHighLevelUtils;
import com.zjhn.ds.utils.base.ApplicationContextHelperUtil;
import com.zjhn.ds.utils.base.CustomUtil;
import com.zjhn.ds.utils.base.RedisCache;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @BelongsProject: ds_jlw
 * @BelongsPackage: com.zjhn.ds.netty.handler
 * @Author: sxt
 * @CreateTime: 2023-09-20  10:06
 * @Description:
 * @Version: 1.0
 */
@Slf4j
@ChannelHandler.Sharable
@Component
public class DeviceServerHandler extends ChannelInboundHandlerAdapter {

    private static RedisCache redisCache;

    private static RestHighLevelUtils restHighLevelUtils;

    /**
     * 当从客户端接收到一个消息时被调用
     * msg 解析后的数据信息
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (redisCache == null)
            redisCache = ApplicationContextHelperUtil.getBean(RedisCache.class);
        if (restHighLevelUtils == null)
            restHighLevelUtils = ApplicationContextHelperUtil.getBean(RestHighLevelUtils.class);

        /* 解析收到数据信息 */
        ByteBuf bb = (ByteBuf) msg;
        // 创建一个和buf同等长度的字节数组
        byte[] reqByte = new byte[bb.readableBytes()];
        bb.readBytes(reqByte); // 将buf中的数据读取到数组中
        String message = CustomUtil.byteArrayToHexStr(reqByte);
        try {
            String ip = ctx.channel().remoteAddress().toString();

            /* 业务处理 01 23 45 67 89 1011 1213 1415 1617 1819 2021 2223 2425 2627 */
            // 数据位1 状态位 01-正常，02-待机，03-故障
            String status = String.valueOf(Integer.parseInt(message.substring(16, 18)));
            String macAddr = message.substring(2, 14);

            List<JSONObject> list = new ArrayList<>();
            String testStatus;
            String preStatus;
            Object maintenanceChange = redisCache.getCacheObject(Constant.REDIS_PRE.MAINTENANCE_CHANGE_STATION + macAddr);
            long current = System.currentTimeMillis();
            if (maintenanceChange != null) {
                status = "3";
                preStatus = "3";
            }else {
                // 获取前一次状态记录  0-关机 1-正常，2-待机，3-故障
                Object preStatusTime = redisCache.getCacheObject(Constant.REDIS_PRE.PRE_STATION_STATUS + macAddr);
                if (preStatusTime != null) {
                    testStatus = status;

                    String[] split = preStatusTime.toString().split("/");
                    preStatus = split[0];
                    long recordTime = Long.parseLong(split[1]);

                    long interval = current - recordTime;

                    if (!"2".equals(preStatus) && "2".equals(status)) {
                        // 前面不是待机状态，当前是待机状态,默认为正常运行状态
                        log.info("===================[INFO]=========!2&2========= mac:{},ip:{},preStatus:{},status:{}", macAddr, ip, preStatus, status);
                        preStatus = status;
                        status = "1";
                    }else if ("2".equals(preStatus) && "2".equals(status) && interval < 30 * 1000) {
                        // 前后都是待机状态，且间隔时间小于30秒，默认为正常运行状态
                        log.info("===================[INFO]========2&2========== mac:{},ip:{},preStatus:{},status:{}", macAddr, ip, preStatus, status);
                        preStatus = status;
                        status = "1";
                    }else {
                        if ("2".equals(status))
                            log.info("===================[INFO]========2222222========== mac:{},ip:{},preStatus:{},status:{}, interval:{}", macAddr, ip, preStatus, status, interval);
                    }

                    list.add(JSONObject.parseObject(JSON.toJSONString(StationStationTimeVo.builder()
                                    .uuid(UUID.randomUUID().toString().replace("-", ""))
                                    .macAddr(macAddr)
                                    .interval(String.valueOf(interval))
                                    .status(testStatus)
                                    .createTime(new Date())
                            .build())));

                } else preStatus = status;
            }

            // 记录上一次状态
            redisCache.setCacheObject(
                    Constant.REDIS_PRE.PRE_STATION_STATUS + macAddr,
                    preStatus + "/" + current,
                    2 * 60
            );

            // 记录当前状态
            redisCache.setCacheObject(Constant.REDIS_PRE.STATION_STATUS + macAddr, status, 2 * 60);

            restHighLevelUtils.multiAddDoc(Constant.ES_INDEX.STATION_STATUS_INDEX, list);

            /* 返回信息 */
            String res = message.substring(0, 26) + "FB";
            byte[] resByte = CustomUtil.hexStringToByteArray(res);
            ctx.writeAndFlush(Unpooled.copiedBuffer(resByte));
        } catch (Exception e) {
            log.error("====[ERROR]========DeviceServerHandler====channelRead0 {}", e.getMessage());
            log.error("====[ERROR]========DeviceServerHandler====channelRead0 message: {}", message);
        }
    }

    /**
     * 在与客户端的连接已经建立之后将被调用
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("====[INFO]========DeviceServerHandler====channelActive channel连接成功，远端地址为：{}", ctx.channel().remoteAddress());
    }


    /**
     * 客户端与服务端断开连接时调用
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        //关闭
        log.info("====[INFO]========DeviceServerHandler====channelInactive {} 客户端连接关闭...", ctx.channel().remoteAddress());
    }

    /**
     * 服务端接收客户端发送过来的数据结束之后调用
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    /**
     * 在处理过程中引发异常时被调用
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("====[INFO]========DeviceServerHandler====exceptionCaught remoteAddress: {},连接异常: {}", ctx.channel().remoteAddress(), cause);
    }
}
